﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Linq;
using SlamCms.Common;

namespace SlamCms.Configuration
{
	internal static class ConfigurationHelpers
	{
		public static void LoadProperties(IConfigurationSettings configuration)
		{
			var currentType = configuration.GetType();
			if (currentType == typeof(EnvironmentConfiguration) || currentType == typeof(SolutionConfiguration))
				return;

			var properties = currentType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)
										.Where(p => IsSystemType(p.PropertyType));

			var missingSettings = new List<string>();

			foreach (var property in properties)
			{
				if (!configuration.Settings.ContainsKey(property.Name))
				{
					missingSettings.Add(property.Name);
					continue;
				}

				var value = configuration.Settings.Get(property.PropertyType, property.Name);

				property.SetValue(configuration, value, null);
			}

			if (missingSettings.Any())
				throw new Exception(string.Format("The following settings are missing in the configuration file:\r\n{0}", string.Join(Environment.NewLine, missingSettings.ToArray())));
		}

		public static T GetEnvironmentSetting<T>(string key, T defaultValue) where T : struct
		{
			try
			{
				return ConfigurationManager.Environment.Settings.Get(key, defaultValue);
			}
			catch (FileNotFoundException)
			{
			}
			catch (DirectoryNotFoundException)
			{
			}
			catch (InvalidCastException)
			{
			}

			return defaultValue;
		}

		private static bool IsSystemType(Type type)
		{
			return type.In(typeof(short), typeof(short?), typeof(ushort), typeof(ushort?),
						   typeof(int), typeof(int?), typeof(uint), typeof(uint?),
						   typeof(long), typeof(long?), typeof(ulong), typeof(ulong?),
						   typeof(bool), typeof(bool?),
						   typeof(decimal), typeof(decimal?),
						   typeof(float), typeof(float?),
						   typeof(double), typeof(double?),
						   typeof(DateTime), typeof(DateTime?),
						   typeof(char), typeof(char?),
						   typeof(string),
						   typeof(Guid));
		}
	}
}
